/* Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "zlang_in.h"

char		_ZLANG_VERSION_0_6_11_0[] = "0.6.11.0" ;
char		*_ZLANG_VERSION = _ZLANG_VERSION_0_6_11_0 ;

char		_zlang_runtime_error_level[10][5+1] = { "DEBUG" , "INFO" , "WARN" , "ERROR" , "FATAL" , "","","","" , "NOLOG" } ;

char		*_zlang_bool_value_str[2] = { ZLANG_OBJECT_bool_false , ZLANG_OBJECT_bool_true } ;

#include "charset_GB18030.c"
#include "charset_UTF8.c"

ZlangInvokeFunction ZlangInvokeFunction_Exit_int;
int ZlangInvokeFunction_Exit_int( struct ZlangRuntime *rt , struct ZlangObject *obj )
{
	struct ZlangObject		*in1 = GetInputParameterInLocalObjectStack(rt,1) ;
	struct ZlangObjectsStackFrame	*first_objs_stack_frame = NULL ;
	int32_t				exit_status ;
	struct ZlangObject		*main_return_obj = NULL ;
	
	CallRuntimeFunction_int_GetIntValue( rt , in1 , & exit_status );
	
	first_objs_stack_frame = GetFirstLocalObjectsStackFrame( rt ) ;
	main_return_obj = rt->local_objs_stack.objs_stack + first_objs_stack_frame->stack_in_params_top ;
	CallRuntimeFunction_int_SetIntValue( rt , main_return_obj , exit_status );
	
	return ZLANG_INFO_EXIT;
}

ZlangInvokeFunction ZlangInvokeFunction_ExitThread_vargs;
int ZlangInvokeFunction_ExitThread_vargs( struct ZlangRuntime *rt , struct ZlangObject *obj )
{
	int				exit_param_count ;
	int				exit_param_index ;
	struct ZlangObject		*in = NULL ;
	
	struct ZlangObjectsStackFrame	*first_objs_stack_frame = NULL ;
	int				stack_no ;
	struct ZlangObject		*out = NULL ;
	
	void				*data = NULL ;
	int32_t				data_len ;
	
	int				nret = 0 ;
	
	exit_param_count = GetInputParameterCountInLocalObjectStack( rt ) ;
	exit_param_index = 1 ;
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "exit_param_count[%d]" , exit_param_count )
	
	first_objs_stack_frame = GetFirstLocalObjectsStackFrame( rt ) ;
	stack_no = first_objs_stack_frame->stack_in_params_top ;
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "stack_no[%d]" , stack_no )
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "first_objs_stack_frame->stack_out_params_top[%d]" , first_objs_stack_frame->stack_out_params_top )
	
	if( exit_param_count != 0 )
	{
		for( ; ; )
		{
			in = GetInputParameterInLocalObjectStack( rt , exit_param_index ) ;
			if( in == NULL )
				break;
			
			if( stack_no >= first_objs_stack_frame->stack_out_params_top )
			{
				TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "stack_no[%d] >= stack_out_params_top[%d]-1" , stack_no , first_objs_stack_frame->stack_out_params_top )
				
				SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "too much return objects" )
				TEST_RUNTIME_DEBUG_THEN_PRINT_INTERRUPT_FUNCTION(rt)
				return ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED;
			}
			
			out = rt->local_objs_stack.objs_stack + stack_no ;
			
			if( IsTypeOf( rt , in , out ) == 0 )
			{
				nret = TryAscensionType( rt , out , & in ) ;
				if( nret == 0 )
				{
					SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_OBJECT_TYPE_NOT_MATCHED , "exit obj[%s]->type_name[%s] type not matched obj[%s]->type_name[%s] type" , GetObjectName(in) , GetCloneObjectName(in) , GetObjectName(out) , GetCloneObjectName(out) )
					TEST_RUNTIME_DEBUG_THEN_PRINT_INTERRUPT_FUNCTION(rt)
					return ZLANG_ERROR_OBJECT_TYPE_NOT_MATCHED;
				}
				else if( nret == 2 )
				{
					TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "TryAscensionType " ); DebugPrintObject(rt,in); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
				}
				else
				{
					TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "TryAscensionType obj[%s] failed" , out->obj_name )
					return GET_RUNTIME_ERROR_NO(rt);
				}
			}
			
			nret = GetDataPtr( rt , in , & data , & data_len );
			if( nret )
			{
				SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_GET_DATA_PTR , "get data ptr failed" )
				TEST_RUNTIME_DEBUG_THEN_PRINT_INTERRUPT_FUNCTION(rt)
				return ZLANG_ERROR_GET_DATA_PTR;
			}
			
			nret = FromDataPtr( rt , out , data , data_len );
			if( nret )
			{
				SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FROM_DATA_PTR , "from data ptr failed" )
				TEST_RUNTIME_DEBUG_THEN_PRINT_INTERRUPT_FUNCTION(rt)
				return ZLANG_ERROR_FROM_DATA_PTR;
			}
			
			TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "set out param " ); DebugPrintObject( rt , out ); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
			
			exit_param_index++;
			stack_no++;
		}
	}
	if( stack_no != first_objs_stack_frame->stack_out_params_top )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "stack_no[%d] != stack_out_params_top[%d]" , stack_no , first_objs_stack_frame->stack_out_params_top )
		
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED , "too little return objects" )
		TEST_RUNTIME_DEBUG_THEN_PRINT_INTERRUPT_FUNCTION(rt)
		return ZLANG_ERROR_FUNC_PARAMETERS_COUNT_NOT_MATCHED;
	}
	
	return ZLANG_INFO_EXIT;
}

static void version()
{
	printf( "zlang v%s build %s %s" NEWLINE , _ZLANG_VERSION , __DATE__ , __TIME__ );
	return;
}

static void usage()
{
	printf( "USAGE : zlang --version" NEWLINE );
	printf( "        zlang [--debug-level|--info-level|--warn-level|--error-level|--fatal-level|--nolog-level] z_source_file" NEWLINE );
	printf( "        zlang --scaffold-main new_z_source_file" NEWLINE );
	printf( "        zlang --git-install url" NEWLINE );
	return;
}

#define RUNNING_MODE_INTERPRET			0
#define RUNNING_MODE_CHECK			1
#define RUNNING_MODE_CHECK_AND_INTERPRET	2

int zlang( int argc , char *argv[] )
{
	struct ZlangRuntime			*rt = NULL ;
	int					cmd_param_idx ;
	char					*source_filename = NULL ;
	
	unsigned char				has_version = 0 ;
	unsigned char				running_modes = RUNNING_MODE_INTERPRET ;
	unsigned char				has_scaffold_main = 0 ;
	char					*git_branch_name = NULL ;
	char					*git_install_makefile = NULL ;
	unsigned char				has_git_install = 0 ;
	
	char					*datapage = NULL ;
	struct ZlangSourceFileDataPageHeader	*source_file_datapage = NULL ;
	struct ZlangTokenDataPageHeader		*token_datapage = NULL ;
	struct ZlangObject			*global_obj = NULL ;
	struct ZlangFunction			*global_func = NULL ;
	struct ZlangIntercept			*intercept = NULL ;
	struct ZlangInterface			*global_interface = NULL ;
	struct ZlangFunctionsEntity		*funcs_enti = NULL ;
	
	struct ZlangFunction			main_func ;
	struct ZlangFunction			*entry_func = NULL ;
	struct ZlangFunctionParameter		*entry_array_paramter = NULL ;
	struct ZlangObjectsStackFrame		*local_objs_stack_frame = NULL ;
	int					local_objs_stack_frame_curridx ;
	struct ZlangObjectsStackFrame		*tmp_objs_stack_frame ;
	int					tmp_objs_stack_frame_curridx ;
	struct ZlangDefersStackFrame		*defers_stack_frame ;
	int					defers_stack_frame_curridx ;
	struct ZlangObject			*main_return_obj = NULL ;
	struct ZlangObject			*main_args_obj = NULL ;
	struct ZlangObject			*main_args_command_param_obj = NULL ;
	int					command_param_len ;
	int32_t					main_return_value ;
	
	struct ZlangIntercept			*next_intercept = NULL ;
	struct ZlangSourceFileDataPageHeader	*next_source_file_datapage = NULL ;
	struct ZlangTokenDataPageHeader		*next_token_datapage = NULL ;
	struct ZlangImportFile			*import_file = NULL ;
	struct ZlangImportFile			*next_import_file = NULL ;
	struct ZlangIncludeFile			*include_file = NULL ;
	struct ZlangIncludeFile			*next_include_file = NULL ;
	struct ZlangObject			*obj = NULL ;
	struct ZlangObject			*next_obj = NULL ;
	
	int					debug_error_level ;
	
	int					nret = 0 ;
	
	if( argc == 1 )
	{
		version();
		printf( NEWLINE );
		usage();
		exit(0);
	}

	rt = ZLMALLOC( sizeof(struct ZlangRuntime) ) ;
	if( rt == NULL )
	{
		printf( "*** ERROR : alloc runtime failed , errno[%d]" NEWLINE , errno );
		return 1;
	}
	memset( rt , 0x00 , sizeof(struct ZlangRuntime) );
	rt->zlang_stack_bottom = (char*) & rt ;
	
	rt->debug_error_level = RUNTIME_ERROR , strcpy( rt->debug_error_level_str , "ERROR" ) ;
	INIT_LIST_HEAD( & (rt->source_file_datapage_list) );
	INIT_LIST_HEAD( & (rt->token_datapage_list) );
	INIT_LIST_HEAD( & (rt->include_files_list) );
	INIT_LIST_HEAD( & (rt->import_files_list) );
	INIT_LIST_HEAD( & (rt->global_order_imported_objs_list) );
	INIT_LIST_HEAD( & (rt->global_intercepts) );
	INIT_LIST_HEAD( & (rt->object_prop_intercepts) );
	INIT_LIST_HEAD( & (rt->global_literal_objs_list) );
	INIT_LIST_HEAD( & (rt->objs_cache) );
	INIT_LIST_HEAD( & (rt->props_entis_cache) );
	INIT_LIST_HEAD( & (rt->funcs_entis_cache) );
	rt->zlang_max_stack_size = atol(ZLANG_MAX_STACK_SIZE) ;
	rt->zlang_alart_stack_depth = (signed long)((double)(rt->zlang_max_stack_size)*0.95) ;
	
	for( cmd_param_idx = 1 ; cmd_param_idx < argc ; cmd_param_idx++ )
	{
		if( STRNCMP( argv[cmd_param_idx] , == , "--" , 2 ) )
		{
			if( STRCMP( argv[cmd_param_idx] , == , "--version" ) )
				has_version = 1 ;
			else if( STRCMP( argv[cmd_param_idx] , == , "--debug-level" ) )
				rt->debug_error_level = RUNTIME_DEBUG , strcpy( rt->debug_error_level_str , "DEBUG" ) ;
			else if( STRCMP( argv[cmd_param_idx] , == , "--info-level" ) )
				rt->debug_error_level = RUNTIME_INFO , strcpy( rt->debug_error_level_str , "INFO" ) ;
			else if( STRCMP( argv[cmd_param_idx] , == , "--warn-level" ) )
				rt->debug_error_level = RUNTIME_WARN , strcpy( rt->debug_error_level_str , "WARN" ) ;
			else if( STRCMP( argv[cmd_param_idx] , == , "--error-level" ) )
				rt->debug_error_level = RUNTIME_ERROR , strcpy( rt->debug_error_level_str , "ERROR" ) ;
			else if( STRCMP( argv[cmd_param_idx] , == , "--fatal-level" ) )
				rt->debug_error_level = RUNTIME_FATAL , strcpy( rt->debug_error_level_str , "FATAL" ) ;
			else if( STRCMP( argv[cmd_param_idx] , == , "--nolog-level" ) )
				rt->debug_error_level = RUNTIME_NOLOG , strcpy( rt->debug_error_level_str , "NOLOG" ) ;
			else if( STRCMP( argv[cmd_param_idx] , == , "--interpret" ) )
				running_modes = RUNNING_MODE_INTERPRET ;
			else if( STRCMP( argv[cmd_param_idx] , == , "--check" ) )
				running_modes = RUNNING_MODE_CHECK ;
			else if( STRCMP( argv[cmd_param_idx] , == , "--check-and-interpret" ) )
				running_modes = RUNNING_MODE_CHECK_AND_INTERPRET ;
			else if( STRCMP( argv[cmd_param_idx] , == , "--scaffold-main" ) )
				has_scaffold_main = 1 ;
			else if( STRCMP( argv[cmd_param_idx] , == , "--git-branch" ) )
			{
				cmd_param_idx++;
				if( cmd_param_idx >= argc )
				{
					printf( "*** ERROR : expect command parameter after '%s'" NEWLINE , argv[cmd_param_idx-1] );
					exit(1);
				}
				git_branch_name = argv[cmd_param_idx] ;
			}
			else if( STRCMP( argv[cmd_param_idx] , == , "--makefile" ) )
			{
				cmd_param_idx++;
				if( cmd_param_idx >= argc )
				{
					printf( "*** ERROR : expect command parameter after '%s'" NEWLINE , argv[cmd_param_idx-1] );
					exit(1);
				}
				git_install_makefile = argv[cmd_param_idx] ;
			}
			else if( STRCMP( argv[cmd_param_idx] , == , "--git-install" ) )
				has_git_install = 1 ;
			else
				printf( "*** ERROR : unknow command parameter '%s'" NEWLINE , argv[cmd_param_idx] );
		}
		else
		{
			break;
		}
	}
	
	if( cmd_param_idx >= argc )
	{
		version();
		usage();
		exit(0);
	}
	
	if( has_version == 1 )
	{
		version();
	}
	
	if( has_scaffold_main == 1 )
	{
		CreateSourceFile_main( argv[cmd_param_idx] );
		exit(0);
	}
	
	if( has_git_install == 1 )
	{
		GitInstall( argv[cmd_param_idx] , git_branch_name , git_install_makefile );
		exit(0);
	}
	
#if ( defined _WIN32 )
	{
		char	*p = NULL ;
		GetModuleFileName( NULL , rt->zlang_pathfilename , sizeof(rt->zlang_pathfilename) );
		p = strrchr(rt->zlang_pathfilename,'\\') ;
		memmove( rt->zlang_pathname , rt->zlang_pathfilename , p-rt->zlang_pathfilename );
		memmove( rt->zlang_filename , p+1 , strlen(p+1)+1 );
	}
#endif
	GetDirectoryWithFileOrCurrentDirectory( argv[cmd_param_idx] , rt->first_z_file_pathname , sizeof(rt->first_z_file_pathname) );
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "zlang v%s , RUN ZLANG-SOURCE[%s] FIRST-Z-FILE-PATH[%s]" , _ZLANG_VERSION , argv[cmd_param_idx] , rt->first_z_file_pathname )
	
	_zlang_rt = rt ;
	
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "--- CREATE STACKS ---" )

	nret = InitObjectStack( rt , & (rt->local_objs_stack) , ZLANG_LOCAL_OBJECTS_STACK_SIZE_DEFAULT , ZLANG_LOCAL_OBJECTS_STACK_INCREASE_SIZE ) ;
	if( nret )
	{
		PRINT_RUNTIME_ERROR( rt , rt->debug_error_level )
		return GET_RUNTIME_ERROR_NO(rt);
	}
	
	nret = InitLocalObjecsStackFrameArray( rt ) ;
	if( nret )
	{
		PRINT_RUNTIME_ERROR( rt , rt->debug_error_level )
		return GET_RUNTIME_ERROR_NO(rt);
	}
	
	local_objs_stack_frame = GetCurrentLocalObjectsStackFrame( rt ) ;
	local_objs_stack_frame_curridx = GetCurrentLocalObjectsStackFrameIndex( rt ) ;
	TEST_RUNTIME_DEBUG( rt )
	{
		PRINT_TABS_AND_FORMAT( rt , "alloc local_objs_stack[%p] ok , local_objs_stack_size[%d] local_objs_stacks_info[%d][%s]-[%d][%d][%d][%d]" , rt->local_objs_stack.objs_stack , rt->local_objs_stack.objs_stack_size , local_objs_stack_frame_curridx , local_objs_stack_frame->full_func_name , local_objs_stack_frame->stack_bottom , local_objs_stack_frame->stack_in_params_top , local_objs_stack_frame->stack_out_params_top , local_objs_stack_frame->stack_local_var_top );
	}
	
	nret = InitObjectStack( rt , & (rt->tmp_objs_stack) , ZLANG_TMP_OBJECTS_STACK_SIZE_DEFAULT , ZLANG_TMP_OBJECTS_STACK_INCREASE_SIZE ) ;
	if( nret )
	{
		PRINT_RUNTIME_ERROR( rt , rt->debug_error_level )
		return GET_RUNTIME_ERROR_NO(rt);
	}
	
	nret = InitTmpObjecsStackFrameArray( rt ) ;
	if( nret )
	{
		PRINT_RUNTIME_ERROR( rt , rt->debug_error_level )
		return GET_RUNTIME_ERROR_NO(rt);
	}
	
	tmp_objs_stack_frame = GetCurrentTmpObjectsStackFrame( rt ) ;
	tmp_objs_stack_frame_curridx = GetCurrentTmpObjectsStackFrameIndex( rt ) ;
	TEST_RUNTIME_DEBUG( rt )
	{
		PRINT_TABS_AND_FORMAT( rt , "alloc tmp_objs_stack[%p] ok , tmp_objs_stack_size[%d] tmp_objs_stacks_info[%d][%s]-[%d][%d][%d][%d]" , rt->tmp_objs_stack.objs_stack , rt->tmp_objs_stack.objs_stack_size , tmp_objs_stack_frame_curridx , tmp_objs_stack_frame->full_func_name , tmp_objs_stack_frame->stack_bottom , tmp_objs_stack_frame->stack_in_params_top , tmp_objs_stack_frame->stack_out_params_top , tmp_objs_stack_frame->stack_local_var_top );
	}
	
	nret = InitDefersStack( rt , & (rt->defers_stack) , ZLANG_DEFERS_STACK_SIZE_DEFAULT , ZLANG_DEFERS_STACK_INCREASE_SIZE ) ;
	if( nret )
	{
		PRINT_RUNTIME_ERROR( rt , rt->debug_error_level )
		return GET_RUNTIME_ERROR_NO(rt);
	}
	
	nret = InitDefersStackFrameArray( rt ) ;
	if( nret )
	{
		PRINT_RUNTIME_ERROR( rt , rt->debug_error_level )
		return GET_RUNTIME_ERROR_NO(rt);
	}
	
	defers_stack_frame = GetCurrentDefersStackFrame( rt ) ;
	defers_stack_frame_curridx = GetCurrentDefersStackFrameIndex( rt ) ;
	TEST_RUNTIME_DEBUG( rt )
	{
		PRINT_TABS_AND_FORMAT( rt , "alloc defers_stack[%p] ok , defers_stack_size[%d] defers_stacks_info[%d][%s]-[%d][%d]" , rt->defers_stack.defers_stack , rt->defers_stack.defers_stack_size , defers_stack_frame_curridx , defers_stack_frame->full_func_name , defers_stack_frame->stack_bottom , defers_stack_frame->stack_top );
	}
	
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "--- LOAD SOURCE FILE ---" )

	datapage = CreateAppendonlyDataPage( ZLANG_SOURCE_FILE_DATAPAGE_MAGIC , ZLANG_SOURCE_FILE_DATAPAGE_SIZE , sizeof(struct ZlangSourceFileDataPageHeader) , 0 , 1 ) ;
	if( datapage == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "create source-file appendonly-datapage failed" )
		PRINT_RUNTIME_ERROR( rt , rt->debug_error_level )
		return ZLANG_ERROR_ALLOC;
	}
	source_file_datapage = GetAppendonlyDataPageUserHeader(datapage) ;
	source_file_datapage->datapage = datapage ;
	list_add_tail( & (source_file_datapage->this_source_file_datapage) , & (rt->source_file_datapage_list) );
	rt->curr_source_file_datapage = source_file_datapage ;
	
	datapage = CreateAppendonlyDataPage( ZLANG_TOKEN_DATAPAGE_MAGIC , ZLANG_TOKEN_DATAPAGE_SIZE , sizeof(struct ZlangTokenDataPageHeader) , sizeof(struct ZlangTokenDataUnitHeader) , 1 ) ;
	if( datapage == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "create token appendonly-datapage failed" )
		PRINT_RUNTIME_ERROR( rt , rt->debug_error_level )
		return ZLANG_ERROR_ALLOC;
	}
	token_datapage = GetAppendonlyDataPageUserHeader(datapage) ;
	token_datapage->datapage = datapage ;
	list_add_tail( & (token_datapage->this_token_datapage) , & (rt->token_datapage_list) );
	rt->curr_token_datapage = token_datapage ;
	
	obj = ZlangImportObject_zobject( rt ) ;
	if( obj == NULL )
	{
		PRINT_RUNTIME_ERROR( rt , rt->debug_error_level )
		return GET_RUNTIME_ERROR_NO(rt);
	}
	
	obj = ZlangImportObject_zruntime( rt ) ;
	if( obj == NULL )
	{
		PRINT_RUNTIME_ERROR( rt , rt->debug_error_level )
		return GET_RUNTIME_ERROR_NO(rt);
	}
	
	ImportCharsetAlias( rt , g_zlang_charset_aliases_GB18030 );
	ImportCharsetAlias( rt , g_zlang_charset_aliases_UTF8 );
	
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "--- LEXICAL ANALYSIS SCAN ---" )
	
	source_filename = argv[cmd_param_idx] ;

	include_file = (struct ZlangIncludeFile *)ZLMALLOC( sizeof(struct ZlangIncludeFile) ) ;
	if( include_file == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "alloc memory for include file" )
		return ZLANG_ERROR_ALLOC;
	}
	memset( include_file , 0x00 , sizeof(struct ZlangIncludeFile) );
	strncpy( include_file->include_filename , source_filename , sizeof(include_file->include_filename)-1 );
	list_add_tail( & (include_file->this_include_file) , & (rt->include_files_list) );
	nret = LexicalAnalysisSourceFile( include_file->include_filename , rt ) ;
	if( nret )
	{
		PRINT_RUNTIME_ERROR( rt , rt->debug_error_level )
		return nret;
	}
	
	cmd_param_idx++;
	
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "--- SYNTAX ANALYSIS SCAN ---" )
	
	nret = SyntaxAnalysisScan( rt ) ;
	if( nret )
	{
		PRINT_RUNTIME_ERROR( rt , rt->debug_error_level )
		return nret;
	}
	
	TEST_RUNTIME_DEBUG( rt )
	{
		DebugLexicalAnalysis( rt );
	}
	
	obj = ZlangImportObject_error( rt ) ;
	if( obj == NULL )
	{
		PRINT_RUNTIME_ERROR( rt , rt->debug_error_level )
		return GET_RUNTIME_ERROR_NO(rt);
	}
	
	obj = ZlangImportObject_fatal( rt ) ;
	if( obj == NULL )
	{
		PRINT_RUNTIME_ERROR( rt , rt->debug_error_level )
		return GET_RUNTIME_ERROR_NO(rt);
	}
	
	AddGlobalFunctionAndParameters( rt , ZlangInvokeFunction_Exit_int , ZLANG_OBJECT_void , ZLANG_FUNCNAME_EXIT , ZLANG_OBJECT_int,NULL , NULL ) ;
	AddGlobalFunctionAndParameters( rt , ZlangInvokeFunction_ExitThread_vargs , ZLANG_OBJECT_void , ZLANG_FUNCNAME_EXITTHREAD , ZLANG_OBJECT_vargs,NULL , NULL ) ;
	
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "PopupTmpObjectsStack" )
	PopupTmpObjectsStackFrame( rt );
	
	if( IsLocalObjectsStackEmpty(rt) && IsTmpObjectsStackEmpty(rt) && IsDefersStackEmpty(rt) )
	{
		;
	}
	else
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_INTERNAL , "stack chaos error" )
		PRINT_RUNTIME_ERROR( rt , rt->debug_error_level )
		return ZLANG_ERROR_INTERNAL;
	}
	
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "--- CHECKING ALL OBJECTS AND FUNCTIONS ---" )

	if( running_modes == RUNNING_MODE_CHECK || running_modes == RUNNING_MODE_CHECK_AND_INTERPRET )
		rt->checking_mode = 1 ;
	main_return_value = 0 ;

	TEST_RUNTIME_DEBUG_OR_CHECKING( rt )
	{
		global_func = NULL ;
		for( ; ; )
		{
			global_func = TravelFunctionInRuntimeFunctionsTreeByFullFunctionName( rt , global_func ) ;
			if( global_func == NULL )
				break;
			
			TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "global function : \n" ); } DebugPrintFunction( rt , NULL , global_func );
		}
	}
	
	TEST_RUNTIME_DEBUG_OR_CHECKING( rt )
	{
		list_for_each_entry( intercept , & (rt->global_intercepts) , struct ZlangIntercept , this_intercept )
		{
			TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "global intercept : \n" ); } DebugPrintIntercept( rt , NULL , intercept );
		}
	}
	
	TEST_RUNTIME_DEBUG_OR_CHECKING( rt )
	{
		list_for_each_entry( intercept , & (rt->object_prop_intercepts) , struct ZlangIntercept , this_intercept )
		{
			TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "object property intercept : \n" ); } DebugPrintIntercept( rt , QueryGlobalObjectByObjectName(rt,intercept->obj_name) , intercept );
		}
	}
	
	TEST_RUNTIME_DEBUG_OR_CHECKING( rt )
	{
		global_interface = NULL ;
		for( ; ; )
		{
			global_interface = TravelInterfaceInRuntimeInterfacesHeapByInterfaceName( rt , global_interface ) ;
			if( global_interface == NULL )
				break;
			
			TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "global interface : \n" ); } DebugPrintInterface( rt , global_interface );
		}
	}
	
	TEST_RUNTIME_DEBUG( rt )
	{
		PRINT_TABS(rt) printf( "global frequent object : obj[%p] obj_name[%s]\n" , rt->frequent_objs.zobject_obj , GetObjectName(rt->frequent_objs.zobject_obj) );
		PRINT_TABS(rt) printf( "global frequent object : obj[%p] obj_name[%s]\n" , rt->frequent_objs.error_obj , GetObjectName(rt->frequent_objs.error_obj) );
		PRINT_TABS(rt) printf( "global frequent object : obj[%p] obj_name[%s]\n" , rt->frequent_objs.fatal_obj , GetObjectName(rt->frequent_objs.fatal_obj) );
		PRINT_TABS(rt) printf( "global frequent object : obj[%p] obj_name[%s]\n" , rt->frequent_objs.string_obj , GetObjectName(rt->frequent_objs.string_obj) );
		PRINT_TABS(rt) printf( "global frequent object : obj[%p] obj_name[%s]\n" , rt->frequent_objs.bool_obj , GetObjectName(rt->frequent_objs.bool_obj) );
		PRINT_TABS(rt) printf( "global frequent object : obj[%p] obj_name[%s]\n" , rt->frequent_objs.short_obj , GetObjectName(rt->frequent_objs.short_obj) );
		PRINT_TABS(rt) printf( "global frequent object : obj[%p] obj_name[%s]\n" , rt->frequent_objs.ushort_obj , GetObjectName(rt->frequent_objs.ushort_obj) );
		PRINT_TABS(rt) printf( "global frequent object : obj[%p] obj_name[%s]\n" , rt->frequent_objs.int_obj , GetObjectName(rt->frequent_objs.int_obj) );
		PRINT_TABS(rt) printf( "global frequent object : obj[%p] obj_name[%s]\n" , rt->frequent_objs.uint_obj , GetObjectName(rt->frequent_objs.uint_obj) );
		PRINT_TABS(rt) printf( "global frequent object : obj[%p] obj_name[%s]\n" , rt->frequent_objs.long_obj , GetObjectName(rt->frequent_objs.long_obj) );
		PRINT_TABS(rt) printf( "global frequent object : obj[%p] obj_name[%s]\n" , rt->frequent_objs.ulong_obj , GetObjectName(rt->frequent_objs.ulong_obj) );
		PRINT_TABS(rt) printf( "global frequent object : obj[%p] obj_name[%s]\n" , rt->frequent_objs.float_obj , GetObjectName(rt->frequent_objs.float_obj) );
		PRINT_TABS(rt) printf( "global frequent object : obj[%p] obj_name[%s]\n" , rt->frequent_objs.double_obj , GetObjectName(rt->frequent_objs.double_obj) );
		PRINT_TABS(rt) printf( "global frequent object : obj[%p] obj_name[%s]\n" , rt->frequent_objs.array_obj , GetObjectName(rt->frequent_objs.array_obj) );
		PRINT_TABS(rt) printf( "global frequent object : obj[%p] obj_name[%s]\n" , rt->frequent_objs.iterator_obj , GetObjectName(rt->frequent_objs.iterator_obj) );
		PRINT_TABS(rt) printf( "global frequent object : obj[%p] obj_name[%s]\n" , rt->frequent_objs.functionptr_obj , GetObjectName(rt->frequent_objs.functionptr_obj) );
	}
	
	if( rt->frequent_objs.string_obj == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_OBJECT_NOT_IMPORTED_OR_DECLARED , "basic object 'string' not imported" )
		PRINT_RUNTIME_ERROR( rt , rt->debug_error_level )
		return ZLANG_ERROR_OBJECT_NOT_IMPORTED_OR_DECLARED;
	}
	if( rt->frequent_objs.bool_obj == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_OBJECT_NOT_IMPORTED_OR_DECLARED , "basic object 'bool' not imported" )
		PRINT_RUNTIME_ERROR( rt , rt->debug_error_level )
		return ZLANG_ERROR_OBJECT_NOT_IMPORTED_OR_DECLARED;
	}
	if( rt->frequent_objs.short_obj == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_OBJECT_NOT_IMPORTED_OR_DECLARED , "basic object 'short' not imported" )
		PRINT_RUNTIME_ERROR( rt , rt->debug_error_level )
		return ZLANG_ERROR_OBJECT_NOT_IMPORTED_OR_DECLARED;
	}
	if( rt->frequent_objs.int_obj == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_OBJECT_NOT_IMPORTED_OR_DECLARED , "basic object 'int' not imported" )
		PRINT_RUNTIME_ERROR( rt , rt->debug_error_level )
		return ZLANG_ERROR_OBJECT_NOT_IMPORTED_OR_DECLARED;
	}
	if( rt->frequent_objs.long_obj == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_OBJECT_NOT_IMPORTED_OR_DECLARED , "basic object 'long' not imported" )
		PRINT_RUNTIME_ERROR( rt , rt->debug_error_level )
		return ZLANG_ERROR_OBJECT_NOT_IMPORTED_OR_DECLARED;
	}
	if( rt->frequent_objs.float_obj == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_OBJECT_NOT_IMPORTED_OR_DECLARED , "basic object 'float' not imported" )
		PRINT_RUNTIME_ERROR( rt , rt->debug_error_level )
		return ZLANG_ERROR_OBJECT_NOT_IMPORTED_OR_DECLARED;
	}
	if( rt->frequent_objs.double_obj == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_OBJECT_NOT_IMPORTED_OR_DECLARED , "basic object 'double' not imported" )
		PRINT_RUNTIME_ERROR( rt , rt->debug_error_level )
		return ZLANG_ERROR_OBJECT_NOT_IMPORTED_OR_DECLARED;
	}
	if( rt->frequent_objs.array_obj == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_OBJECT_NOT_IMPORTED_OR_DECLARED , "basic object 'array' not imported" )
		PRINT_RUNTIME_ERROR( rt , rt->debug_error_level )
		return ZLANG_ERROR_OBJECT_NOT_IMPORTED_OR_DECLARED;
	}
	if( rt->frequent_objs.iterator_obj == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_OBJECT_NOT_IMPORTED_OR_DECLARED , "basic object 'iterator' not imported" )
		PRINT_RUNTIME_ERROR( rt , rt->debug_error_level )
		return ZLANG_ERROR_OBJECT_NOT_IMPORTED_OR_DECLARED;
	}
	if( rt->frequent_objs.functionptr_obj == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_OBJECT_NOT_IMPORTED_OR_DECLARED , "basic object 'functionptr' not imported" )
		PRINT_RUNTIME_ERROR( rt , rt->debug_error_level )
		return ZLANG_ERROR_OBJECT_NOT_IMPORTED_OR_DECLARED;
	}
	
	TEST_RUNTIME_DEBUG_OR_CHECKING( rt )
	{
		global_obj = NULL ;
		for( ; ; )
		{
			global_obj = TravelObjectInRuntimeObjectsHeapByObjectName( rt , global_obj ) ;
			if( global_obj == NULL )
				break;
			TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "global object : " ); DebugPrintObject( rt , global_obj ); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
			
			DebugPrintObjectProperties( rt , global_obj );
			
			funcs_enti = GetObjectFunctionsEntity(global_obj) ;
			DebugPrintFunctionsEntity( rt , global_obj , funcs_enti );
		}
	}
	
	if( GetCheckingErrorNo( rt ) )
	{
		main_return_value = GetCheckingErrorNo( rt ) ;
		goto _GOTO_CLEAN_RUNTIME_ENVIRONMENT;
	}
	if( running_modes == RUNNING_MODE_CHECK )
	{
		goto _GOTO_CLEAN_RUNTIME_ENVIRONMENT;
	}
	
	if( IsLocalObjectsStackEmpty(rt) && IsTmpObjectsStackEmpty(rt) && IsDefersStackEmpty(rt) )
	{
		;
	}
	else
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_INTERNAL , "stack chaos error" )
		PRINT_RUNTIME_ERROR( rt , rt->debug_error_level )
		return ZLANG_ERROR_INTERNAL;
	}

	rt->checking_mode = 0 ;

	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "--- QUERY MAIN FUNCTION ---" )
	
	memset( & main_func , 0x00 , sizeof(struct ZlangFunction) );
	main_func.full_func_name = ZLANG_FULLFUNCNAME_MAIN ;
	entry_func = QueryFunctionInRuntimeFunctionsTreeByFullFunctionName( rt , & main_func ) ;
	if( entry_func == NULL )
	{
		main_func.full_func_name = ZLANG_FULLFUNCNAME_MAIN_GB18030 ;
		entry_func = QueryFunctionInRuntimeFunctionsTreeByFullFunctionName( rt , & main_func ) ;
		if( entry_func == NULL )
		{
			main_func.full_func_name = ZLANG_FULLFUNCNAME_MAIN_UTF8 ;
			entry_func = QueryFunctionInRuntimeFunctionsTreeByFullFunctionName( rt , & main_func ) ;
			if( entry_func == NULL )
			{
				SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_NOT_FOUND , "no main func" )
				PRINT_RUNTIME_ERROR( rt , rt->debug_error_level )
				return GET_RUNTIME_ERROR_NO(rt);
			}
		}
	}
	
	TEST_RUNTIME_DEBUG( rt )
	{
		PRINT_TABS_AND_FORMAT( rt , "find main function[%p] ok" , entry_func );
	}
	
	SetObjectsStackFullFuncName( local_objs_stack_frame , main_func.full_func_name );
	SetObjectsStackFullFuncName( tmp_objs_stack_frame , main_func.full_func_name );
	SetDefersStackFullFuncName( defers_stack_frame , main_func.full_func_name );
	
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "--- PREPARE MAIN FUNCTION PARAMETERS ---" )

	entry_array_paramter = list_first_entry_or_null( & (entry_func->in_params) , struct ZlangFunctionParameter , this_param ) ;
	if( entry_array_paramter == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FUNC_NOT_FOUND , "invalid main func prototype" )
		PRINT_RUNTIME_ERROR( rt , rt->debug_error_level )
		return GET_RUNTIME_ERROR_NO(rt);
	}
	main_args_obj = CloneArrayObjectInLocalStack( rt , entry_array_paramter->obj_name ) ;
	if( main_args_obj == NULL )
	{
		PRINT_RUNTIME_ERROR( rt , rt->debug_error_level )
		return nret;
	}
	TEST_RUNTIME_DEBUG( rt )
	{
		PRINT_TABS(rt) printf( "CreateArrayObjectInLocalStack ok " ); DebugPrintObject(rt,main_args_obj); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE
	}
	local_objs_stack_frame->stack_in_params_top = local_objs_stack_frame->stack_local_var_top ;
	
	main_return_obj = CloneIntObjectInLocalStack( rt , NULL ) ;
	if( main_return_obj == NULL )
	{
		PRINT_RUNTIME_ERROR( rt , rt->debug_error_level )
		return nret;
	}
	TEST_RUNTIME_DEBUG( rt )
	{
		PRINT_TABS(rt) printf( "CreateIntObjectInLocalStack ok " ); DebugPrintObject(rt,main_return_obj); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE
	}
	local_objs_stack_frame->stack_out_params_top = local_objs_stack_frame->stack_local_var_top ;
	
	for( ; cmd_param_idx < argc ; cmd_param_idx++ )
	{
		main_args_command_param_obj = NULL ;
		nret = CloneObject( rt , & main_args_command_param_obj , NULL , GetStringObjectInRuntimeObjectsHeap(rt) ) ;
		if( nret )
		{
			PRINT_RUNTIME_ERROR( rt , rt->debug_error_level )
			return ZLANG_ERROR_CREATE_OBJECT;
		}
		TEST_RUNTIME_DEBUG( rt )
		{
			PRINT_TABS_AND_FORMAT( rt , "CreateStringObject ok" );
		}
		
		command_param_len = (int)strlen(argv[cmd_param_idx]) ;
		nret = FromCharPtr( rt , main_args_command_param_obj , argv[cmd_param_idx] , command_param_len ) ;
		if( nret )
		{
			PRINT_RUNTIME_ERROR( rt , rt->debug_error_level )
			return nret;
		}
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "FormCharPtr[%d][%.*s] to string object" , command_param_len , command_param_len,argv[cmd_param_idx] )
		
		nret = CallRuntimeFunction_array_Append( rt , main_args_obj , main_args_command_param_obj , NULL ) ;
		if( nret )
		{
			PRINT_RUNTIME_ERROR( rt , rt->debug_error_level )
			return nret;
		}
		TEST_RUNTIME_DEBUG( rt )
		{
			PRINT_TABS(rt) printf( "CallDirectFunction_array_Append ok " ); DebugPrintObject(rt,main_args_command_param_obj); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE
		}
		
		DestroyObject( rt , main_args_command_param_obj );
	}
	
	TEST_RUNTIME_DEBUG( rt )
	{
		DebugStack( rt );
	}
	
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "--- CALL MAIN FUNCTION ---" )
	
	rt->in_obj = NULL ;
	rt->in_func = entry_func ;
	rt->travel_token_datapage_header = entry_func->func_begin_token_datapage_header ;
	rt->travel_token_dataunit = entry_func->func_begin_token_dataunit ;
	SetObjectsStackCallerTokenInfo( rt );
	nret = InterpretStatementSegment( rt , NULL ) ;
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "main function throw fatal[%d]" , HaveFatalException(rt) )
	if( HaveFatalException(rt) )
	{
		char	*message = NULL ;
		char	*exception_source_filename = NULL ;
		int32_t	exception_source_row ;
		int32_t	exception_source_col ;
		char	*exception_obj_name = NULL ;
		char	*exception_func_name = NULL ;
		char	*stack_trace = NULL ;
		GetFatalMessage( rt , & message );
		GetFatalExceptionSourceFilename( rt , & exception_source_filename );
		GetFatalExceptionSourceRow( rt , & exception_source_row );
		GetFatalExceptionSourceColumn( rt , & exception_source_col );
		GetFatalExceptionObjectName( rt , & exception_obj_name );
		GetFatalExceptionFunctionName( rt , & exception_func_name );
		GetFatalStackTrace( rt , & stack_trace );
		printf( "*** FATAL EXCEPTION CATCHED\n" );
		printf( "*** EXCEPTION SOURCE : %s:%d,%d\n" , exception_source_filename , exception_source_row , exception_source_col );
		printf( "*** EXCEPTION FUNCTION : [%s][%s]\n" , exception_obj_name , exception_func_name );
		printf( "*** MESSAGE : %s\n" , message );
		printf( "%s" , stack_trace );
		main_return_value = ZLANG_ERROR_THROW_FATAL ;
	}
	else
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "main function throw error[%d]" , HaveErrorException(rt) )
		if( HaveErrorException(rt) )
		{
			char	*message = NULL ;
			char	*exception_source_filename = NULL ;
			int32_t	exception_source_row ;
			int32_t	exception_source_col ;
			char	*exception_obj_name = NULL ;
			char	*exception_func_name = NULL ;
			char	*stack_trace = NULL ;
			GetErrorMessage( rt , & message );
			GetErrorExceptionSourceFilename( rt , & exception_source_filename );
			GetErrorExceptionSourceRow( rt , & exception_source_row );
			GetErrorExceptionSourceColumn( rt , & exception_source_col );
			GetErrorExceptionObjectName( rt , & exception_obj_name );
			GetErrorExceptionFunctionName( rt , & exception_func_name );
			GetErrorStackTrace( rt , & stack_trace );
			printf( "*** ERROR EXCEPTION CATCHED\n" );
			printf( "*** EXCEPTION SOURCE : %s:%d,%d\n" , exception_source_filename , exception_source_row , exception_source_col );
			printf( "*** EXCEPTION FUNCTION : [%s][%s]\n" , exception_obj_name , exception_func_name );
			printf( "*** MESSAGE : %s\n" , message );
			printf( "%s" , stack_trace );
			main_return_value = ZLANG_ERROR_THROW_ERROR ;
		}
		else
		{
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "main function return[%d]" , nret )
			if( nret == ZLANG_INFO_CONTINUE )
			{
				SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_CONTINUE_NOT_WITHIN_LOOP_OR_SWITCH , "continue not within loop or switch" )
				PRINT_RUNTIME_ERROR( rt , rt->debug_error_level )
				main_return_value = nret ;
			}
			else if( nret == ZLANG_INFO_BREAK )
			{
				SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_BREAK_NOT_WITHIN_LOOP_OR_SWITCH , "break not within loop or switch" )
				PRINT_RUNTIME_ERROR( rt , rt->debug_error_level )
				main_return_value = nret ;
			}
			else if( nret == ZLANG_INFO_END_OF_STATEMENT_SEGMENT || nret == ZLANG_INFO_EXIT )
			{
				CallRuntimeFunction_int_GetIntValue( rt , main_return_obj , & main_return_value );
			}
			else
			{
				char	err_buf[ 1024 ] ;
				memset( err_buf , 0x00 , sizeof(err_buf) );
				FillRuntimeErrorString( rt , err_buf , sizeof(err_buf) );
				printf( "%s\n" , err_buf );
				main_return_value = nret ;
			}
		}
	}
	
	TEST_RUNTIME_DEBUG( rt )
	{
		DebugStack( rt );
	}
	
_GOTO_CLEAN_RUNTIME_ENVIRONMENT :

	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "--- CLEAN RUNTIME ENVIRONMENT ---" )

	global_obj = NULL ;
	for( ; ; )
	{
		global_obj = TravelObjectInRuntimeObjectsHeapByObjectName( rt , global_obj ) ;
		if( global_obj == NULL )
			break;
		
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "DestractObject[%s]" , GetObjectName(global_obj) )
		DestractObject( rt , global_obj );
	}
	
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "PopupDefersStack" )
	PopupDefersStackFrame( rt );
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "PopupLocalObjectsStack" )
	PopupLocalObjectsStackFrame( rt );
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "PopupTmpObjectsStack" )
	PopupTmpObjectsStackFrame( rt );
	
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CleanObjectsStack local_objs_stack" )
	CleanObjectsStack( rt , & (rt->local_objs_stack) );
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CleanLocalObjecsStackFrameArray" )
	CleanLocalObjecsStackFrameArray( rt );
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CleanObjectsStack tmp_objs_stack" )
	CleanObjectsStack( rt , & (rt->tmp_objs_stack) );
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CleanTmpObjecsStackFrameArray" )
	CleanTmpObjecsStackFrameArray( rt );
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CleanDefersStack defers_stack" )
	CleanDefersStack( rt , & (rt->defers_stack) );
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CleanDefersStackFrameArray" )
	CleanDefersStackFrameArray( rt );
	
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "DestroyRuntimeObjectsHeap" )
	DestroyRuntimeObjectsHeap( rt );
	
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "DestroyRuntimeFunctionsTree" )
	DestroyRuntimeFunctionsTreeByFunctionName( rt );
	DestroyRuntimeFunctionsTreeByFullFunctionName( rt );
	
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "destroy all intercept" )
	list_for_each_entry_safe( intercept , next_intercept , & (rt->global_intercepts) , struct ZlangIntercept , this_intercept )
	{
		ZLFREE( intercept->obj_name );
		ZLFREE( intercept->func_name );
		FreeFunction( intercept->func );
		
		ZLFREE( intercept );
	}
	list_for_each_entry_safe( intercept , next_intercept , & (rt->object_prop_intercepts) , struct ZlangIntercept , this_intercept )
	{
		ZLFREE( intercept->obj_name );
		ZLFREE( intercept->func_name );
		FreeFunction( intercept->func );
		
		ZLFREE( intercept );
	}
	list_for_each_entry_safe( obj , next_obj , & (rt->global_literal_objs_list) , struct ZlangObject , obj_list_node )
	{
		DestroyObject( rt , obj );
	}
	DestroyRuntimeInterfacesHeap( rt );
	
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "destroy all charset alias" )
	DestroyRuntimeCharsetAlias( rt );
	
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "FreeObjectsCache" )
	FreeObjectsCache( rt );
	
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "FreePropertiesEntityCache" )
	FreePropertiesEntityCache( rt );
	
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "FreeFunctionsEntityCache" )
	FreeFunctionsEntityCache( rt );
	
	memset( & (rt->travel_token_info) , 0x00 , sizeof(struct ZlangTokenDataUnitHeader) );
	
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "destroy all import" )
	list_for_each_entry_safe( import_file , next_import_file , & (rt->import_files_list) , struct ZlangImportFile , this_import_file )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "dlclose[%s][%p] and ZLFREE import file[%p]" , import_file->import_filename,import_file->open_handler , import_file )
		list_del( & (import_file->this_import_file) );
#if defined(__linux__)
		TEST_RUNTIME_DEBUG(rt)
		{
		}
		else
		{
			dlclose( import_file->open_handler );
		}
#elif defined(_WIN32)
		TEST_RUNTIME_DEBUG(rt)
		{
		}
		else
		{
			FreeLibrary( import_file->open_handler );
		}
#endif
		ZLFREE( import_file );
	}
	
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "destroy all include" )
	list_for_each_entry_safe( include_file , next_include_file , & (rt->include_files_list) , struct ZlangIncludeFile , this_include_file )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "ZLFREE include file[%p][%s]" , include_file , include_file->include_filename )
		list_del( & (include_file->this_include_file) );
		ZLFREE( include_file );
	}
	
	if( main_return_value < 0 )
		main_return_value = -main_return_value ;
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "RUN ZLANG-SOURCE[%s] EXIT-STATUS[%d]" , source_filename , main_return_value )
	
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "destroy all source file datapage" )
	list_for_each_entry_safe( source_file_datapage , next_source_file_datapage , & (rt->source_file_datapage_list) , struct ZlangSourceFileDataPageHeader , this_source_file_datapage )
	{
		list_del( & (source_file_datapage->this_source_file_datapage) );
		DestroyAppendonlyDataPage( source_file_datapage->datapage );
	}
	
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "destroy all token datapage" )
	list_for_each_entry_safe( token_datapage , next_token_datapage , & (rt->token_datapage_list) , struct ZlangTokenDataPageHeader , this_token_datapage )
	{
		list_del( & (token_datapage->this_token_datapage) );
		DestroyAppendonlyDataPage( token_datapage->datapage );
	}
	
	if( rt->full_charset_str )
	{
		ZLFREE( rt->full_charset_str );
	}
	
	debug_error_level = rt->debug_error_level ;
	ZLFREE( rt );
	
	if( debug_error_level <= RUNTIME_DEBUG )
	{
		DebugPrintRawMemory();
	}
	
	return main_return_value;
}

